C++ オブジェクトのライフサイクルを理解することは、 ヒープとスタックにおける存在そのもののメカニズムを掌握することです。コピー制御は、クラスが ライフサイクル を2つの操作を通じて管理する方法を定義します: コピーコンストラクタ および コピーアサインメント演算子。
1. 初期化と代入の違い
直接初期化(例: string dots(10, '.'))はコンストラクタを直接呼び出します。しかし、 コピーオブジェクト初期化 (string s2 = dots)はコピーコンストラクタに依存します。初期化とは異なり、 代入 (trans = accum)は既存のオブジェクトを、 operator=を使って上書きします。重要な制約として、コピーコンストラクタのパラメータは参照型(const Foo&)でなければなりません。そうでない場合、値渡しで引数を渡すと、 無限再帰ループ コピー呼び出しの無限ループが発生します。
2. 自動生成の役割
これらのメンバ関数を定義しない場合、コンパイラが 自動生成された メンバーワイズコピーを行うバージョンを提供します。注意:シンプルな型には十分ですが、動的メモリを管理するクラスではしばしば失敗し、ダングリングポインタや二重解放の原因になります。
main.py
TERMINALbash — 80x24
> Ready. Click "Run" to execute.
>
QUESTION 1
Why must the first parameter of a copy constructor be a reference type (usually const)?
To allow the compiler to optimize the code into a move operation.
To prevent infinite recursion during parameter initialization.
Because pointers are not allowed in constructor signatures.
To ensure the object is placed on the heap rather than the stack.
✅ Correct!
Correct! If the parameter were passed by value, calling the copy constructor would require a copy of the argument, which would call the copy constructor again, infinitely.❌ Incorrect
Think about how arguments are passed. Passing by value requires a copy... and how is that copy made?QUESTION 2
What is the primary difference between Copy Initialization and Direct Initialization?
Direct initialization uses the assignment operator; copy initialization does not.
Copy initialization always requires the 'new' keyword.
Direct initialization asks the compiler to find the best constructor; copy initialization requires the copy constructor.
There is no functional difference; they are just different syntax for the same call.
✅ Correct!
Exactly. Copy initialization happens when using '=', passing by value, or returning by value, and specifically requires the copy/move constructor.❌ Incorrect
Direct initialization (using parens or braces) matches against all available constructors, while copy initialization specifically invokes the copy constructor.QUESTION 3
Assume 'numbered' has a synthesized copy constructor that copies a unique ID 'mysn'. What happens if you run: numbered a, b = a, c = b;?
Each object (a, b, c) will have a unique 'mysn' value.
The program will fail to compile because IDs cannot be copied.
All three objects will share the exact same 'mysn' value.
Object 'a' will be reset to zero after the copy.
✅ Correct!
Since the synthesized version performs memberwise copy, it simply duplicates the value of 'mysn' from the source, defeating the uniqueness.❌ Incorrect
The synthesized copy constructor does not 'know' that 'mysn' is supposed to be unique; it just copies the bits.QUESTION 4
Which of the following would trigger a compilation error if the constructor 'vector<int>(int size)' is marked 'explicit'?
vector<int> v(10);vector<int> v = 10;f(vector<int>(10));vector<int>* p = new vector<int>(10);✅ Correct!
Correct! 'explicit' prevents the use of a constructor in copy-initialization contexts (like using '=').❌ Incorrect
Explicit constructors can be used for direct initialization but not for implicit conversions or copy initialization using '='.QUESTION 5
What should a well-behaved copy-assignment operator usually return?
void
A copy of the current object by value.
A reference to the left-hand operand (*this).
The memory address of the right-hand operand.
✅ Correct!
This is a best practice to remain consistent with built-in types and allow assignment chaining (e.g., a = b = c).❌ Incorrect
To allow chaining and maintain standard C++ behavior, return a reference to the modified object.Case Study: Identifying Copy Logistics
Trace object construction and assignment
Analyze the following snippet:
Point global;
Point foo_bar(Point arg) {
Point local = arg;
Point *heap = new Point(global);
*heap = local;
Point pa[2] = { local, *heap };
return *heap;
}
Q
1. How many times is the copy constructor called in the execution of foo_bar?
Solution:
The copy constructor is called 6 times: 1. Passing 'arg' by value. 2. Initializing 'local'. 3. Dynamic construction of '*heap' from 'global'. 4. Initializing pa[0]. 5. Initializing pa[1]. 6. Initializing the return value from '*heap'.
The copy constructor is called 6 times: 1. Passing 'arg' by value. 2. Initializing 'local'. 3. Dynamic construction of '*heap' from 'global'. 4. Initializing pa[0]. 5. Initializing pa[1]. 6. Initializing the return value from '*heap'.
Q
2. Does the line '*heap = local' use the copy constructor?
Solution:
No. This is an assignment operation on an already existing object pointed to by 'heap'. It uses the copy-assignment operator (
No. This is an assignment operation on an already existing object pointed to by 'heap'. It uses the copy-assignment operator (
operator=), not the copy constructor.Q
3. If the 'Message' class used synthesized copy control while managing a list of 'Folders', what potential danger arises?
Solution:
A 'shallow copy' would occur. The new 'Message' would point to the same internal resources as the old one, but the 'Folders' wouldn't know about the new message. This leads to broken links or double-free errors when the messages are destroyed.
A 'shallow copy' would occur. The new 'Message' would point to the same internal resources as the old one, but the 'Folders' wouldn't know about the new message. This leads to broken links or double-free errors when the messages are destroyed.